Skip to main content

Navigation And Layout

Introduction

These components move the user around an app and frame its pages:

  • DcTabs: tabs that switch between panels.
  • DcCategoryTabs: a tab strip with optional icons and an actions area.
  • DcNavigationDrawer: a sidebar list of links.
  • DcBreadcrumbs: a trail of router links.
  • DcTreeNavigation: a tree of nodes that can expand, with optional lazy loading.
  • DcPageHeader: the banner at the top of a section, with a title, description, icon and actions.
  • DcCollapsibleSidePanel: a side panel that folds down to a thin rail.
  • DcBlueHeaderBar and DcCardBlueContainer: a light blue bar with left and right slots.

Import them from the kit registry. The examples assume a component in apps/myapp/components/.


DcTabs​

DcTabs shows a row of tabs and one panel per tab. Each panel is a named slot whose name is the tab's key.

import { DcTabs } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcTabs },
data() {
return {
tab: "details",
tabs: [
{ name: "Details", key: "details" },
{ name: "History", key: "history" },
],
};
},
template: `
<dc-tabs :tabs="tabs" v-model="tab" @tab_changed="onTabChanged">
<template #details>Order details</template>
<template #history>Order history</template>
</dc-tabs>`,
methods: {
onTabChanged(tab) {
// tab is the clicked object, e.g. { name: "History", key: "history" }
},
},
};

Props

NameTypeDefaultDescription
tabsArray[]One object per tab: name (the label) and key (the slot name).
modelValueNumber, StringundefinedThe active tab, matched against each tab's model_key field. Use v-model.
model_keyString"name"The tab field that v-model reads and writes.

Events

EventPayloadWhen
update:modelValueThe clicked tab's model_key value, lowercased when it is a stringA tab is clicked.
tab_changedThe clicked tab objectA tab is clicked.

Slots

SlotContent
one per tab, named by its keyThat tab's panel.

All panels are rendered at once and the inactive ones are hidden with CSS, so every panel's components mount when the tabs do.


DcCategoryTabs​

DcCategoryTabs is a tab strip for switching between categories. Each tab can show an image icon, and an actions slot sits at the right end of the strip. The panel content goes in the holder slot, which receives the active tab's index.

import { DcCategoryTabs } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcCategoryTabs },
data() {
return {
category: "overview",
tabs: [{ label: "Overview" }, { label: "Properties" }],
};
},
template: `
<dc-category-tabs :tabs="tabs" v-model="category">
<template #holder="{ active_tab }">
<div v-if="active_tab === 0">Overview panel</div>
<div v-else>Properties panel</div>
</template>
</dc-category-tabs>`,
};

Props

NameTypeDefaultDescription
tabsArraynullOne object per tab: label, and optionally icon, an image URL shown 20px wide.
modelValueNumber, StringnoneThe active tab, matched case-insensitively against each tab's model_key field. Use v-model.
model_keyString"label"The tab field that v-model reads and writes. Use a lowercase field name.

Events

EventPayloadWhen
update:modelValueThe clicked tab's model_key value, lowercasedA tab is clicked.
tab_changedThe clicked tab objectA tab is clicked.

Slots

SlotScopeContent
holderactive_tab: the active tab's indexThe panel content.
actionsnoneControls at the right end of the tab strip.

DcNavigationDrawer​

DcNavigationDrawer is a card with a title and a scrollable list of links, for an app's sidebar. Bind v-model to the selected item's key so the selection follows the route.

import { DcNavigationDrawer } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcNavigationDrawer },
data() {
return {
items: [
{ key: "orders", title: "Orders", icon: "fa-receipt" },
{ key: "customers", title: "Customers", icon: "fa-users" },
{ heading: true, title: "Settings" },
{ key: "general", title: "General", icon: "fa-gear" },
],
};
},
computed: {
selected() {
return this.$route.name;
},
},
template: `
<dc-navigation-drawer :items="items" :model-value="selected" label="Orders navigation" compact
@change_navigation="(item) => $router.push({ name: item.key })">
<template #navigator_title>Orders</template>
</dc-navigation-drawer>`,
};

Props

NameTypeDefaultDescription
itemsArraynullOne object per row: title, icon (a Font Awesome icon name such as fa-inbox; the fa-solid style is added for you) and the key field named by itemKey. A row with heading: true is a group label, not a link.
modelValueString, NumberundefinedThe selected item's key. Use v-model. While it is undefined, the drawer highlights the row last clicked instead.
itemKeyString"key"The item field that v-model reads and writes.
compactBooleanfalseA denser layout with tighter rows and a tinted selected row.
labelString"Navigation"The aria-label of the list.
scrollContainerIdStringdc-navigation-<n>The id of the scrolling element. Each drawer gets its own, so two drawers can share a page.
loadingBooleanfalseShows a loader over the list.
navigation_item_classString, FunctionnullExtra classes for each row. A function is called with (item, index) and returns the classes.
selected_navigation_itemStringnullThe index of the row to highlight when v-model isn't used. See the note below.
hide_iconsBooleanfalseHides the row icons.
show_bulletsBooleanfalseAdds the show-bullets class to the list.
show_lineBooleanfalseAdds the show-line class to the list.
nav_container_classString""Extra classes for the scrolling element.

Events

EventPayloadWhen
update:modelValueThe item's itemKey valueA row is clicked, or chosen with Enter or Space.
change_navigation(item, index)Same as above.
scrolled_to"Bottom"The list is scrolled to the bottom.

Slots

SlotScopeContent
navigator_titlenoneThe drawer's title.
navigator_buttonnoneA control to the right of the title.
navigation-titleitem, indexReplaces a row's title text.
custom-navigation-itemsitem, indexExtra content under a row's title.
custom-nav-container-slotnoneContent under the list, inside the scrolling area, such as a DcTreeNavigation.

The admin panel has an older copy of this component. It has no v-model, itemKey, compact, label, scrollContainerId, show_bullets, show_line or heading rows, and doesn't emit scrolled_to.


DcBreadcrumbs​

DcBreadcrumbs renders a trail of router-links with a chevron between them.

import { DcBreadcrumbs } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcBreadcrumbs },
data() {
return {
crumbs: [
{ text: "Orders", link: { name: "myapp_orders" } },
{ text: "ORD-1042", link: { name: "myapp_order", params: { id: 1042 } } },
],
};
},
template: `<dc-breadcrumbs :items="crumbs" />`,
};

Props

NameTypeDefaultDescription
itemsArrayrequiredOne object per crumb: text and link, any router-link target. An item without text renders as an empty entry.

It has no events or slots.


DcTreeNavigation​

DcTreeNavigation shows nested nodes that expand and collapse. It can load a node's children on demand. Arrow keys move between rows, Right and Left expand and collapse, Home and End jump to the ends, and Enter or Space selects.

import { DcTreeNavigation } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcTreeNavigation },
data() {
return {
selected: null,
expanded: ["projects"],
nodes: [
{ id: "projects", label: "Projects", icon: "fa-regular fa-folder-open", children: [
{ id: "design", label: "Design", icon: "fa-regular fa-folder" },
{ id: "archive", label: "Archive", icon: "fa-regular fa-folder", hasChildren: true },
] },
],
};
},
methods: {
async loadChildren(node) {
// Call your app's service and return an array of nodes. Throw to show the error and Retry.
return [];
},
},
template: `
<dc-tree-navigation v-model="selected" v-model:expanded-keys="expanded"
:nodes="nodes" :load-children="loadChildren" label="Project folders" />`,
};

A node is { id, label, icon?, disabled?, children?, hasChildren? }. IDs must be unique across the tree. A node with hasChildren: true and no children calls loadChildren(node) the first time it is expanded. The result is cached. To discard the cached children, for example when you switch to another dataset, give the component a new key.

Props

NameTypeDefaultDescription
nodesArray[]The root nodes.
modelValueString, NumbernullThe selected node's id. Use v-model.
expandedKeysArraynullThe ids of the expanded nodes. Use v-model:expanded-keys. When it is null, the tree keeps its own state.
loadChildrenFunctionnullCalled with a node. Returns an array of child nodes, or a Promise of one.
labelString"Navigation tree"The tree's aria-label.
loadingBooleanfalseShows loadingText under the root nodes.
emptyTextString"No items."Shown when there are no root nodes, or a node has no children.
loadingTextString"Loading..."Shown while nodes load.
errorTextString"Could not load items."Shown when loadChildren fails.
retryTextString"Retry"The label of the retry button.

Events

EventPayloadWhen
update:modelValueThe node's idA node is selected.
update:expandedKeysThe new array of expanded idsA node expands or collapses.
selectThe nodeA node is selected.
toggle{ node, expanded }A node expands or collapses.
load-error{ node, error }loadChildren throws, rejects or doesn't return an array.

Slots

SlotScopeContent
labelnode, selectedReplaces a node's label.
actionsnodeControls at the end of each row. Clicks on them don't select the row.

DcPageHeader​

DcPageHeader is the banner at the top of a section: a title, a short description, an icon, and the page's actions at the top right.

import { DcPageHeader, DcButton } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcPageHeader, DcButton },
template: `
<dc-page-header title="Orders" description="Orders placed in the last 30 days." icon="fa-regular fa-receipt">
<template #actions>
<dc-button @click="createOrder">Create Order</dc-button>
</template>
</dc-page-header>`,
methods: {
createOrder() {
// Open your create form.
},
},
};

Props

NameTypeDefaultDescription
titleStringrequiredThe heading.
descriptionString""The line under the heading.
iconString""Font Awesome classes for the icon, such as fa-regular fa-receipt.

It has no events.

Slots

SlotContent
actionsButtons at the top right.
iconReplaces the icon.
descriptionReplaces the description text.

DcCollapsibleSidePanel​

DcCollapsibleSidePanel wraps content beside the main column, such as an activity feed. A toggle folds it to a thin rail that shows the title.

import { DcCollapsibleSidePanel } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcCollapsibleSidePanel },
data() {
return { collapsed: false };
},
template: `
<div class="dcui-flex-item">
<div class="dcui-flex-1">Main content</div>
<dc-collapsible-side-panel v-model:collapsed="collapsed" title="Activity" :expand-below="900">
Panel content
</dc-collapsible-side-panel>
</div>`,
};

Props

NameTypeDefaultDescription
collapsedBooleanfalseWhether the panel is folded. Use v-model:collapsed.
sideString"right"right or left. Sets which way the toggle's chevron points.
titleString""Shown on the folded rail, and used in the toggle's aria-label.
expandBelowNumber0At or below this viewport width in pixels, the panel is always open and the toggle is hidden. 0 turns this off.

Events

EventPayloadWhen
update:collapsedThe new folded stateThe toggle or the rail is clicked.

Slots

SlotContent
defaultThe panel content.
collapsed-railReplaces the title on the folded rail.

On a narrow screen, expand-below only changes what is shown. Your collapsed value is left alone, so the user's choice comes back when the screen widens.

The admin panel registry doesn't export DcCollapsibleSidePanel.


DcBlueHeaderBar​

DcBlueHeaderBar is a card with a light blue background and two slots, one on each side. Use it for a toolbar strip above a list.

import { DcBlueHeaderBar, DcButton } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcBlueHeaderBar, DcButton },
template: `
<dc-blue-header-bar>
<template #left><strong>12 orders</strong></template>
<template #right><dc-button>Export</dc-button></template>
</dc-blue-header-bar>`,
};

It has no props or events.

Slots

SlotContent
leftContent on the left.
rightContent on the right.

DcCardBlueContainer​

DcCardBlueContainer is identical to DcBlueHeaderBar: the same light blue card with left and right slots. Use either; there is no difference between them.

import { DcCardBlueContainer } from "../../xp_system/components/dc_ui_kit_componenets/dc_ui_kit_registry.js";

export default {
components: { DcCardBlueContainer },
template: `
<dc-card-blue-container>
<template #left>Left content</template>
<template #right>Right content</template>
</dc-card-blue-container>`,
};

It has no props or events.

Slots

SlotContent
leftContent on the left.
rightContent on the right.